home *** CD-ROM | disk | FTP | other *** search
- /* -*- mode: C; tab-width:8; -*-
-
- fxrender.c - 3Dfx VooDoo RenderVB driver function support
- */
-
- /*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * See the file fxapi.c for more informations about authors
- *
- */
-
- #if defined(FX)
-
- #include "fxdrv.h"
-
- /*
- * Render a line segment from VB[v1] to VB[v2] when either one or both
- * endpoints must be clipped.
- */
- static void fxRenderClippedLine( GLcontext *ctx, GLuint v1, GLuint v2 )
- {
- GLfloat ndc_x,ndc_y,ndc_z;
- struct vertex_buffer *VB=ctx->VB;
- fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
- GrVertex *gWin=fxMesa->gWin;
-
- /*
- * Clipping may introduce new vertices. New vertices will be stored
- * in the vertex buffer arrays starting with location VB->Free. After
- * we've rendered the line, these extra vertices can be overwritten.
- */
- VB->Free = VB_MAX;
-
- /* Clip against view volume */
- if (gl_viewclip_line( ctx, &v1, &v2 )==0)
- return;
-
- /* Transform from clip coords to ndc: ndc = clip / W */
- if (VB->Clip[v1][3] != 0.0F) {
- GLfloat wInv = 1.0F / VB->Clip[v1][3];
- ndc_x = VB->Clip[v1][0] * wInv;
- ndc_y = VB->Clip[v1][1] * wInv;
- ndc_z = VB->Clip[v1][2] * wInv;
- } else {
- /* Can't divide by zero, so... */
- ndc_x = ndc_y = ndc_z = 0.0F;
- }
-
- /* Map ndc coord to window coords. */
- VB->Win[v1][0] = ndc_x * ctx->Viewport.Sx + ctx->Viewport.Tx;
- VB->Win[v1][1] = ndc_y * ctx->Viewport.Sy + ctx->Viewport.Ty;
- VB->Win[v1][2] = ndc_z * ctx->Viewport.Sz + ctx->Viewport.Tz;
-
- /* Transform from clip coords to ndc: ndc = clip / W */
- if (VB->Clip[v2][3] != 0.0F) {
- GLfloat wInv = 1.0F / VB->Clip[v2][3];
- ndc_x = VB->Clip[v2][0] * wInv;
- ndc_y = VB->Clip[v2][1] * wInv;
- ndc_z = VB->Clip[v2][2] * wInv;
- } else {
- /* Can't divide by zero, so... */
- ndc_x = ndc_y = ndc_z = 0.0F;
- }
-
- /* Map ndc coord to window coords. */
- VB->Win[v2][0] = ndc_x * ctx->Viewport.Sx + ctx->Viewport.Tx;
- VB->Win[v2][1] = ndc_y * ctx->Viewport.Sy + ctx->Viewport.Ty;
- VB->Win[v2][2] = ndc_z * ctx->Viewport.Sz + ctx->Viewport.Tz;
-
- (*ctx->Driver.RasterSetup)(ctx,v1,v1+1);
- (*ctx->Driver.RasterSetup)(ctx,v2,v2+1);
-
- grDrawLine(&gWin[v1],&gWin[v2]);
- }
-
- /*
- * Render a polygon in which at least one vertex has to be clipped.
- * Input: n - number of vertices
- * vlist - list of vertices in the polygon.
- * CCW order = front facing.
- */
- static void fxRenderClippedPolygon( GLcontext *ctx, GLuint n, GLuint vlist[] )
- {
- struct vertex_buffer *VB = ctx->VB;
- GLfloat (*win)[3] = VB->Win;
- fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
- GrVertex *gWin=fxMesa->gWin;
-
- /*
- * Clipping may introduce new vertices. New vertices will be stored
- * in the vertex buffer arrays starting with location VB->Free. After
- * we've rendered the polygon, these extra vertices can be overwritten.
- */
- VB->Free = VB_MAX;
-
- /* Clip against view volume in clip coord space */
- n = gl_viewclip_polygon( ctx, n, vlist );
- if (n<3)
- return;
-
- /* Transform new vertices from clip to ndc to window coords. */
- /* ndc = clip / W window = viewport_mapping(ndc) */
- /* Note that window Z values are scaled to the range of integer */
- /* depth buffer values. */
- {
- GLfloat sx = ctx->Viewport.Sx;
- GLfloat tx = ctx->Viewport.Tx;
- GLfloat sy = ctx->Viewport.Sy;
- GLfloat ty = ctx->Viewport.Ty;
- GLfloat sz = ctx->Viewport.Sz;
- GLfloat tz = ctx->Viewport.Tz;
- GLuint i;
-
- /* Only need to compute window coords for new vertices */
- for (i=VB_MAX; i<VB->Free; i++) {
- if (VB->Clip[i][3] != 0.0F) {
- GLfloat wInv = 1.0F / VB->Clip[i][3];
- win[i][0] = VB->Clip[i][0] * wInv * sx + tx;
- win[i][1] = VB->Clip[i][1] * wInv * sy + ty;
- win[i][2] = VB->Clip[i][2] * wInv * sz + tz;
- }
- else {
- /* Can't divide by zero, so... */
- win[i][0] = win[i][1] = win[i][2] = 0.0F;
- }
- }
-
- if(VB->Free > VB_MAX)
- (*ctx->Driver.RasterSetup)(ctx,VB_MAX,VB->Free);
- }
-
- {
- GLint i;
- GLuint j0=vlist[0];
-
- for (i=2;i<n;i++)
- grDrawTriangle(&gWin[j0],&gWin[vlist[i-1]],&gWin[vlist[i]]);
- }
- }
-
- /************************************************************************/
- /************************ RenderVB functions ****************************/
- /************************************************************************/
-
- #undef FXRENDERVB_NAME
- #undef RVB_COLOR
- #define FXRENDERVB_NAME fxDDRenderVBFlat
- #define RVB_COLOR(pv) grConstantColorValue(FXCOLOR(VB->Color[pv][0], \
- VB->Color[pv][1], \
- VB->Color[pv][2], \
- VB->Color[pv][3]));
- #include "fxrender.h"
-
- #undef FXRENDERVB_NAME
- #undef RVB_COLOR
- #define FXRENDERVB_NAME fxDDRenderVBSmooth
- #define RVB_COLOR(pv)
- #include "fxrender.h"
-
- #undef FXRENDERVB_NAME
- #undef RVB_COLOR
-
- tfxRenderVBFunc fxDDChooseRenderVBFunction(GLcontext *ctx)
- {
- fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
-
- if((ctx->RasterMask & FRONT_AND_BACK_BIT) ||
- (ctx->Polygon.OffsetAny) || /* Not yet supported */
- (ctx->Light.Model.TwoSide) ||
- (ctx->Transform.AnyClip) ||
- (ctx->Point.SmoothFlag) ||
- (ctx->Line.SmoothFlag) ||
- (ctx->Polygon.Unfilled) ||
- (ctx->Polygon.SmoothFlag) ||
- (ctx->Polygon.StippleFlag) ||
- (ctx->RenderMode!=GL_RENDER)) {
- grCullMode(GR_CULL_DISABLE);
- return NULL;
- }
-
- fxMesa->currentFrontFace=ctx->Polygon.FrontFace;
-
- if(ctx->Polygon.CullFlag) {
- switch(ctx->Polygon.CullFaceMode) {
- case GL_BACK:
- if(ctx->Polygon.FrontFace==GL_CCW)
- grCullMode(GR_CULL_NEGATIVE);
- else
- grCullMode(GR_CULL_POSITIVE);
- break;
- case GL_FRONT:
- if(ctx->Polygon.FrontFace==GL_CCW)
- grCullMode(GR_CULL_POSITIVE);
- else
- grCullMode(GR_CULL_NEGATIVE);
- break;
- case GL_FRONT_AND_BACK:
- grCullMode(GR_CULL_DISABLE);
- return NULL;
- default:
- ; /*nothing*/
- }
- } else
- grCullMode(GR_CULL_DISABLE);
-
- if(ctx->Light.ShadeModel==GL_SMOOTH)
- return fxDDRenderVBSmooth;
-
- return fxDDRenderVBFlat;
- }
-
-
- #else
-
-
- /*
- * Need this to provide at least one external definition.
- */
-
- int gl_fx_dummy_function_render(void)
- {
- return 0;
- }
-
- #endif /* FX */
-